/*
 * Copyright (c) 2013-2018 上海汇数数据. All rights reserved.
 * @(#) AbstractRecording.java 2018-08-10 23:44
 */

package com.jh.user.pojo.freeQuick;

import cn.jh.common.core.data.domain.Recording;
import cn.jh.common.core.support.jpa.Jsr310Converters;
import com.google.common.base.MoreObjects;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.AbstractPersistable;

import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.MappedSuperclass;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import static cn.jh.common.core.io.ExternalizableKt.intBitMask;
import static cn.jh.common.core.io.ExternalizableKt.isFieldPresent;


/**
 * @author Fuchun
 * @since 1.0
 */
@MappedSuperclass
public abstract class AbstractRecording<PK extends Serializable> extends AbstractPersistable<PK>
        implements Recording {

    private static final long serialVersionUID = 1L;

    @Column(name = "updated_at")
    @Convert(converter = Jsr310Converters.LocalDateTimeConverter.class)
    @LastModifiedDate
    private LocalDateTime updatedAt;
    @Column(name = "created_at")
    @Convert(converter = Jsr310Converters.LocalDateTimeConverter.class)
    @CreatedDate
    private LocalDateTime createdAt;

    @Override
    public void setId(PK id) {
        super.setId(id);
    }

    @Override
    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    @Override
    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }

    @Override
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    @Override
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }

    protected MoreObjects.ToStringHelper mapRecording(MoreObjects.ToStringHelper tsh) {
        return tsh
                .add("updatedAt", getUpdatedAt())
                .add("createdAt", getCreatedAt());
    }

    protected void writeRecording(ObjectOutput out) throws IOException {
        LocalDateTime updatedAt = getUpdatedAt();
        LocalDateTime createdAt = getCreatedAt();
        if (updatedAt != null) {
            String updatedAtString = updatedAt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            out.writeUTF(updatedAtString);
        }
        if (createdAt != null) {
            String createdAtString = createdAt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            out.writeUTF(createdAtString);
        }
    }

    protected void readRecording(ObjectInput in, int bitMask, int startIndex) throws IOException {
        if (isFieldPresent(bitMask, startIndex)) {
            String updatedAtString = in.readUTF();
            setUpdatedAt(LocalDateTime.parse(updatedAtString, DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }
        if (isFieldPresent(bitMask, startIndex + 1)) {
            String createdAtString = in.readUTF();
            setCreatedAt(LocalDateTime.parse(createdAtString, DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }
    }

    protected int recordingBitMask(int bitMask, int startIndex) {
        int newVal = getUpdatedAt() != null ? bitMask | intBitMask(startIndex) : bitMask;
        newVal = getCreatedAt() != null ? newVal | intBitMask(startIndex + 1) : newVal;
        return newVal;
    }
}
